import functinn as fun
import numpy as np
import pandas as pd
import scipy.io as sio
from scipy.optimize import minimize

data = sio.loadmat('data/ex4data1.mat')
raw_x = data['X']
raw_y = data['y']

X = np.insert(raw_x, 0, values=1, axis=1)
y = fun.one_hot_encoding(raw_y)
# print(f"X的维度:{X.shape},y的维度:{y.shape}")

# 获取训练参数
theta = sio.loadmat('data/ex4weights.mat')
theta1 = theta['Theta1']
theta2 = theta['Theta2']


# print(f"theta1的维度:{theta1.shape},theta2的维度:{theta2.shape}")


# 激活函数求导
def sigmoid_gradient(z):
    return fun.sigmoid(z) * (1 - fun.sigmoid(z))


def gradient(theta_serialize, X, y):
    a1, z1, a2, z2, a3 = fun.forward(theta=theta_serialize, X=X)
    d3 = a3 - y
    d2 = d3 @ theta2[:, 1:] * sigmoid_gradient(z1)
    D2 = (d3.T @ a2) / len(X)
    D1 = (d2.T @ a1) / len(X)
    return fun.serialize(D1, D2)


init_theta = np.random.uniform(-0.5, 0.5, 10285)  # 权值随机初始化
res = minimize(
    fun=fun.cost,
    x0=init_theta,
    args=(X, y),
    method='TNC',
    jac=gradient,
    options={'maxiter': 300}
)

# theta3, theta4 = fun.deserialize(res.x)
# data1 = pd.DataFrame(theta4)
# writer = pd.ExcelWriter('data/A.xlsx')
# data1.to_excel(writer, 'page_1')
# writer.save()
# writer.close()
raw_y = data['y'].reshape(5000, )
_, _, _, _, h = fun.forward(res.x, X)

y_pre = np.argmax(h, axis=1) + 1
acc = np.mean(y_pre == raw_y)
print(acc)
